﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CamShared;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net;
using DavuxLib;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Diagnostics;

namespace DirectShow
{
    public class DirectShow : ICameraConnector, IDisposable
    {

        public void DetectCameras()
        {
            List<ICamera> cams = new List<ICamera>();
            try
            {
                FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                for (int i = 0; i < videoDevices.Count; i++)
                {
                    DirectShowCamera dc = new DirectShowCamera(new VideoCaptureDevice(videoDevices[i].MonikerString), videoDevices[i].Name, videoDevices[i].MonikerString);
                    CameraDiscovered(dc, this);
                }
            }
            catch(Exception ex)
            {
                Trace.WriteLine("Error detecting local cameras: " + ex);
            }
        }

        // not supported for this type of camera
        public ICamera CreateCamera(string Name, string Class, string[] args)
        {
            return null;
        }

        public string Name
        {
            get { return "Local Camera"; }
        }

        public void Dispose()
        {

        }


        #region ICameraConnector Members

        public event CamShared.CamShared.CameraDiscovered CameraDiscovered;

        #endregion
    }

    public class DirectShowCamera : BaseCamera
    {


        public override bool ShowConfig(IntPtr handle) { vd.DisplayPropertyPage(handle); return true; }



        VideoCaptureDevice vd = null;
        public DirectShowCamera(VideoCaptureDevice vd, string Name, string devName)
        {
            this.Name = Name;
            this.vd = vd;
            this.Class = "USB/PCI Camera";

            VideoCapabilities vc = vd.VideoCapabilities[0];



            vd.DesiredFrameRate = Settings.Get(Name + "|DesiredFrameRate", vc.MaxFrameRate);
            vd.DesiredFrameSize = new Size(Settings.Get(Name + "|Width", vc.FrameSize.Width),
                Settings.Get(Name + "|Height", vc.FrameSize.Height));

            Settings.Get(Name + "|Recording Height", vc.FrameSize.Height);
            Settings.Get(Name + "|Recording Width", vc.FrameSize.Height);

            vd.NewFrame += new NewFrameEventHandler(vd_NewFrame);
            vd.VideoSourceError += new VideoSourceErrorEventHandler(vd_VideoSourceError);
            vd.PlayingFinished += new PlayingFinishedEventHandler(vd_PlayingFinished);

            //Settings.SetRestartRequired(Name + "|DesiredFrameRate");
           // Settings.SetRestartRequired(Name + "|Width");
            //Settings.SetRestartRequired(Name + "|Height");
        }

        void vd_PlayingFinished(object sender, ReasonToFinishPlaying reason)
        {
            ErrorArrived(this, reason.ToString(), true);
        }

        void vd_VideoSourceError(object sender, VideoSourceErrorEventArgs eventArgs)
        {
            ErrorArrived(this, eventArgs.Description, true);
        }

        void vd_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            Bitmap b = (Bitmap)eventArgs.Frame.Clone();
            eventArgs.Frame.Dispose();
            FrameArrived(this, b);
        }

        protected override void OnActivated()
        {
            vd.Start();
        }

        protected override void OnDeActivated()
        {
            vd.SignalToStop();
            vd.Stop();
        }
    }
}
